package component.traverse;

import java.util.*;

import component.AbstractComponent;
import component.group.ComponentGroup;

public class Traverse {

	private ComponentGroup border = null;
	
	private List<TraverseListener> listeners = new LinkedList<TraverseListener>();
	
	
	public void setBorder(ComponentGroup border) {
		if (border == null)
			this.border = null;
		else
			this.border = new ComponentGroup(border);
	}
	
	public void addListener(TraverseListener listener) {
		listeners.add(listener);
	}
	
	private boolean notifyListeners(AbstractComponent component, Object command) {
		boolean c = true;
		for (TraverseListener listener : listeners) {
			c = c && listener.traverseNode(component, command);
		}
		return c;
	}
	
	private boolean isBorderNode(AbstractComponent component) {
		if (border == null) return false;
		return border.contains(component);
	}
	
	public void traverse(AbstractComponent startComponent, Object command) {
		Set<AbstractComponent> visited = new HashSet<AbstractComponent>();
		this.traverse(startComponent, null, visited, command);
	}
	
	private void traverse(AbstractComponent component, AbstractComponent previous, Set<AbstractComponent> visited, Object command) {
		if (isBorderNode(component)) return;
		if (visited.contains(component)) return;
		
		if (!notifyListeners(component, command)) return;
		visited.add(component);
		
		for (AbstractComponent child : component.getConnectedComponents()) {
			if (child != previous)
				traverse(child, component, visited, command);
		}
	}
	
}
